using System;
using System.Collections;
using Scenario.WorkflowEngine.DataModel;

namespace Scenario.WorkflowEngine.DataModel.WorkflowRelevantData
{
	//*********************************************************************
	//
	// XmlVariables Class
	//
	// The XmlVariables class represents a collection base of XmlVariable
	// Its imports methods from WAPI.XmlObjectSet like get set and add
	// XmlVariables Has no fields
	//
	//*********************************************************************

	public class XMLAttributes : bOS.XML.Data.XMLObjectSet
	{
		public const string MAIN_NODE		= "Attributes";

		/** FIELDS **/

		/** no fields **/

		/** CONSTRUCTORS **/

		/** CONSTRUCTOR Empty **/
		public XMLAttributes()
		{
			this.Init();
		}

		/** CONSTRUCTOR Width xml parsering**/
		public XMLAttributes(System.Xml.XmlNode nodeList)
		{
			this.Parse (nodeList);
		}

		/** INSTANCE METHODS **/

		public override void Init()
		{
			this.RemoveAll();
		}

		/**Method to parse an xml string into a nodelist collection **/
		override public void Parse(System.Xml.XmlNode nodeList)
		{
			this.Init();

			System.Xml.XmlNode node;

			for ( int i=0; i<nodeList.ChildNodes.Count;i++)
			{
				node = nodeList.ChildNodes[i];

				switch ( node.Name) 
				{
					case XMLAttribute.MAIN_NODE:
						this.Add ( new XMLAttribute(node));
						break;
				}
			}
		}

		/**Method to retive a nodelist from collection **/
		override public bOS.XML.XMLNode GetXMLNode()
		{
			bOS.XML.XMLNode xmlNode = new bOS.XML.XMLNode(XMLAttributes.MAIN_NODE);

			for ( int i=0; i<this.Count;i++)
			{
				xmlNode.AddNode ( this[i].GetXMLNode() );
			}

			return xmlNode;
		}

		/** Method for return a functionParameter from collection **/
		public XMLAttribute Get(String sAttributeName)
		{
			for ( int i=0; i<this.Count;i++)
			{
				XMLAttribute attribute = (XMLAttribute)this.List[i];

				if ( attribute.Name == sAttributeName )
				{
					return attribute;
				}
			}

			throw new Scenario.WorkflowEngine.DataModel.Exception.AttributeNotFound("Impossible to find attribute");
		}

		public bool AddAttribute (XMLAttribute attribute2Add)
		{
			for ( int i=0; i<this.Count;i++)
			{
				XMLAttribute attribute = (XMLAttribute)this.List[i];

				if ( attribute.Name == attribute2Add.Name )
				{
					return false;
				}
			}

			this.Add ( attribute2Add );

			return true;
		}

		public bool AddAttribute(string _Name, string _Type, string _Direction)
		{
			for ( int i=0; i<this.Count;i++)
			{
				XMLAttribute attribute = (XMLAttribute)this.List[i];

				if ( attribute.Name == _Name )
				{
					return false;
				}
			}

			this.Add ( new XMLAttribute(_Name, _Type, _Direction) );

			return true;
		}

		public void AddAttributes (XMLAttributes attributes2Add)
		{
			for ( int i=0; i<attributes2Add.Count;i++)
			{
				XMLAttribute attribute = (XMLAttribute)attributes2Add[i];

				this.AddAttribute (attribute);
			}
		}

		/** Instance methods to check if a Attribute is in collection **/

		/** TODO 
		almost in
		**/

		/** SORTING  FIELDS **/

		public enum SortFields 
		{
			Name,
			Type,
			Direction,
			Value
		}

		/** SORTING METHODS **/


		public void Sort(SortFields sortField, bool isAscending) 
		{
			switch (sortField) 
			{
				case SortFields.Name:
					InnerList.Sort(new NameComparer());
					break;
				case SortFields.Type:
					InnerList.Sort(new TypeComparer());
					break;
				case SortFields.Direction:
					InnerList.Sort(new DirectionComparer());
					break;
				case SortFields.Value:
					InnerList.Sort(new ValueComparer());
					break;
			}
			if (!isAscending) InnerList.Reverse();
		}


		private sealed class NameComparer : IComparer 
		{
			public int Compare(object x, object y) 
			{
				XMLAttribute first = (XMLAttribute) x;
				XMLAttribute second = (XMLAttribute) y;
				return first.Name.CompareTo(second.Name);
			}
		}

		private sealed class TypeComparer : IComparer 
		{
			public int Compare(object x, object y) 
			{
				XMLAttribute first = (XMLAttribute) x;
				XMLAttribute second = (XMLAttribute) y;
				return first.Type.CompareTo(second.Type);
			}
		}

		private sealed class DirectionComparer : IComparer 
		{
			public int Compare(object x, object y) 
			{
				XMLAttribute first = (XMLAttribute) x;
				XMLAttribute second = (XMLAttribute) y;
				return first.Direction.CompareTo(second.Direction);
			}
		}

		private sealed class ValueComparer : IComparer 
		{
			public int Compare(object x, object y) 
			{
				XMLAttribute first = (XMLAttribute) x;
				XMLAttribute second = (XMLAttribute) y;
				return first.Value.CompareTo(second.Value);
			}
		}
	}
}
